home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / scripts / mod / sumversion.c < prev   
Encoding:
C/C++ Source or Header  |  2008-12-24  |  11.7 KB  |  507 lines

  1. #include <netinet/in.h>
  2. #ifdef __sun__
  3. #include <inttypes.h>
  4. #else
  5. #include <stdint.h>
  6. #endif
  7. #include <ctype.h>
  8. #include <errno.h>
  9. #include <string.h>
  10. #include <limits.h>
  11. #include "modpost.h"
  12.  
  13. /*
  14.  * Stolen form Cryptographic API.
  15.  *
  16.  * MD4 Message Digest Algorithm (RFC1320).
  17.  *
  18.  * Implementation derived from Andrew Tridgell and Steve French's
  19.  * CIFS MD4 implementation, and the cryptoapi implementation
  20.  * originally based on the public domain implementation written
  21.  * by Colin Plumb in 1993.
  22.  *
  23.  * Copyright (c) Andrew Tridgell 1997-1998.
  24.  * Modified by Steve French (sfrench@us.ibm.com) 2002
  25.  * Copyright (c) Cryptoapi developers.
  26.  * Copyright (c) 2002 David S. Miller (davem@redhat.com)
  27.  * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
  28.  *
  29.  * This program is free software; you can redistribute it and/or modify
  30.  * it under the terms of the GNU General Public License as published by
  31.  * the Free Software Foundation; either version 2 of the License, or
  32.  * (at your option) any later version.
  33.  *
  34.  */
  35. #define MD4_DIGEST_SIZE        16
  36. #define MD4_HMAC_BLOCK_SIZE    64
  37. #define MD4_BLOCK_WORDS        16
  38. #define MD4_HASH_WORDS        4
  39.  
  40. struct md4_ctx {
  41.     uint32_t hash[MD4_HASH_WORDS];
  42.     uint32_t block[MD4_BLOCK_WORDS];
  43.     uint64_t byte_count;
  44. };
  45.  
  46. static inline uint32_t lshift(uint32_t x, unsigned int s)
  47. {
  48.     x &= 0xFFFFFFFF;
  49.     return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
  50. }
  51.  
  52. static inline uint32_t F(uint32_t x, uint32_t y, uint32_t z)
  53. {
  54.     return (x & y) | ((~x) & z);
  55. }
  56.  
  57. static inline uint32_t G(uint32_t x, uint32_t y, uint32_t z)
  58. {
  59.     return (x & y) | (x & z) | (y & z);
  60. }
  61.  
  62. static inline uint32_t H(uint32_t x, uint32_t y, uint32_t z)
  63. {
  64.     return x ^ y ^ z;
  65. }
  66.  
  67. #define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s))
  68. #define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (uint32_t)0x5A827999,s))
  69. #define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (uint32_t)0x6ED9EBA1,s))
  70.  
  71. /* XXX: this stuff can be optimized */
  72. static inline void le32_to_cpu_array(uint32_t *buf, unsigned int words)
  73. {
  74.     while (words--) {
  75.         *buf = ntohl(*buf);
  76.         buf++;
  77.     }
  78. }
  79.  
  80. static inline void cpu_to_le32_array(uint32_t *buf, unsigned int words)
  81. {
  82.     while (words--) {
  83.         *buf = htonl(*buf);
  84.         buf++;
  85.     }
  86. }
  87.  
  88. static void md4_transform(uint32_t *hash, uint32_t const *in)
  89. {
  90.     uint32_t a, b, c, d;
  91.  
  92.     a = hash[0];
  93.     b = hash[1];
  94.     c = hash[2];
  95.     d = hash[3];
  96.  
  97.     ROUND1(a, b, c, d, in[0], 3);
  98.     ROUND1(d, a, b, c, in[1], 7);
  99.     ROUND1(c, d, a, b, in[2], 11);
  100.     ROUND1(b, c, d, a, in[3], 19);
  101.     ROUND1(a, b, c, d, in[4], 3);
  102.     ROUND1(d, a, b, c, in[5], 7);
  103.     ROUND1(c, d, a, b, in[6], 11);
  104.     ROUND1(b, c, d, a, in[7], 19);
  105.     ROUND1(a, b, c, d, in[8], 3);
  106.     ROUND1(d, a, b, c, in[9], 7);
  107.     ROUND1(c, d, a, b, in[10], 11);
  108.     ROUND1(b, c, d, a, in[11], 19);
  109.     ROUND1(a, b, c, d, in[12], 3);
  110.     ROUND1(d, a, b, c, in[13], 7);
  111.     ROUND1(c, d, a, b, in[14], 11);
  112.     ROUND1(b, c, d, a, in[15], 19);
  113.  
  114.     ROUND2(a, b, c, d,in[ 0], 3);
  115.     ROUND2(d, a, b, c, in[4], 5);
  116.     ROUND2(c, d, a, b, in[8], 9);
  117.     ROUND2(b, c, d, a, in[12], 13);
  118.     ROUND2(a, b, c, d, in[1], 3);
  119.     ROUND2(d, a, b, c, in[5], 5);
  120.     ROUND2(c, d, a, b, in[9], 9);
  121.     ROUND2(b, c, d, a, in[13], 13);
  122.     ROUND2(a, b, c, d, in[2], 3);
  123.     ROUND2(d, a, b, c, in[6], 5);
  124.     ROUND2(c, d, a, b, in[10], 9);
  125.     ROUND2(b, c, d, a, in[14], 13);
  126.     ROUND2(a, b, c, d, in[3], 3);
  127.     ROUND2(d, a, b, c, in[7], 5);
  128.     ROUND2(c, d, a, b, in[11], 9);
  129.     ROUND2(b, c, d, a, in[15], 13);
  130.  
  131.     ROUND3(a, b, c, d,in[ 0], 3);
  132.     ROUND3(d, a, b, c, in[8], 9);
  133.     ROUND3(c, d, a, b, in[4], 11);
  134.     ROUND3(b, c, d, a, in[12], 15);
  135.     ROUND3(a, b, c, d, in[2], 3);
  136.     ROUND3(d, a, b, c, in[10], 9);
  137.     ROUND3(c, d, a, b, in[6], 11);
  138.     ROUND3(b, c, d, a, in[14], 15);
  139.     ROUND3(a, b, c, d, in[1], 3);
  140.     ROUND3(d, a, b, c, in[9], 9);
  141.     ROUND3(c, d, a, b, in[5], 11);
  142.     ROUND3(b, c, d, a, in[13], 15);
  143.     ROUND3(a, b, c, d, in[3], 3);
  144.     ROUND3(d, a, b, c, in[11], 9);
  145.     ROUND3(c, d, a, b, in[7], 11);
  146.     ROUND3(b, c, d, a, in[15], 15);
  147.  
  148.     hash[0] += a;
  149.     hash[1] += b;
  150.     hash[2] += c;
  151.     hash[3] += d;
  152. }
  153.  
  154. static inline void md4_transform_helper(struct md4_ctx *ctx)
  155. {
  156.     le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(uint32_t));
  157.     md4_transform(ctx->hash, ctx->block);
  158. }
  159.  
  160. static void md4_init(struct md4_ctx *mctx)
  161. {
  162.     mctx->hash[0] = 0x67452301;
  163.     mctx->hash[1] = 0xefcdab89;
  164.     mctx->hash[2] = 0x98badcfe;
  165.     mctx->hash[3] = 0x10325476;
  166.     mctx->byte_count = 0;
  167. }
  168.  
  169. static void md4_update(struct md4_ctx *mctx,
  170.                const unsigned char *data, unsigned int len)
  171. {
  172.     const uint32_t avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
  173.  
  174.     mctx->byte_count += len;
  175.  
  176.     if (avail > len) {
  177.         memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
  178.                data, len);
  179.         return;
  180.     }
  181.  
  182.     memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
  183.            data, avail);
  184.  
  185.     md4_transform_helper(mctx);
  186.     data += avail;
  187.     len -= avail;
  188.  
  189.     while (len >= sizeof(mctx->block)) {
  190.         memcpy(mctx->block, data, sizeof(mctx->block));
  191.         md4_transform_helper(mctx);
  192.         data += sizeof(mctx->block);
  193.         len -= sizeof(mctx->block);
  194.     }
  195.  
  196.     memcpy(mctx->block, data, len);
  197. }
  198.  
  199. static void md4_final_ascii(struct md4_ctx *mctx, char *out, unsigned int len)
  200. {
  201.     const unsigned int offset = mctx->byte_count & 0x3f;
  202.     char *p = (char *)mctx->block + offset;
  203.     int padding = 56 - (offset + 1);
  204.  
  205.     *p++ = 0x80;
  206.     if (padding < 0) {
  207.         memset(p, 0x00, padding + sizeof (uint64_t));
  208.         md4_transform_helper(mctx);
  209.         p = (char *)mctx->block;
  210.         padding = 56;
  211.     }
  212.  
  213.     memset(p, 0, padding);
  214.     mctx->block[14] = mctx->byte_count << 3;
  215.     mctx->block[15] = mctx->byte_count >> 29;
  216.     le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
  217.                       sizeof(uint64_t)) / sizeof(uint32_t));
  218.     md4_transform(mctx->hash, mctx->block);
  219.     cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(uint32_t));
  220.  
  221.     snprintf(out, len, "%08X%08X%08X%08X",
  222.          mctx->hash[0], mctx->hash[1], mctx->hash[2], mctx->hash[3]);
  223. }
  224.  
  225. static inline void add_char(unsigned char c, struct md4_ctx *md)
  226. {
  227.     md4_update(md, &c, 1);
  228. }
  229.  
  230. static int parse_string(const char *file, unsigned long len,
  231.             struct md4_ctx *md)
  232. {
  233.     unsigned long i;
  234.  
  235.     add_char(file[0], md);
  236.     for (i = 1; i < len; i++) {
  237.         add_char(file[i], md);
  238.         if (file[i] == '"' && file[i-1] != '\\')
  239.             break;
  240.     }
  241.     return i;
  242. }
  243.  
  244. static int parse_comment(const char *file, unsigned long len)
  245. {
  246.     unsigned long i;
  247.  
  248.     for (i = 2; i < len; i++) {
  249.         if (file[i-1] == '*' && file[i] == '/')
  250.             break;
  251.     }
  252.     return i;
  253. }
  254.  
  255. /* FIXME: Handle .s files differently (eg. # starts comments) --RR */
  256. static int parse_file(const char *fname, struct md4_ctx *md)
  257. {
  258.     char *file;
  259.     unsigned long i, len;
  260.  
  261.     file = grab_file(fname, &len);
  262.     if (!file)
  263.         return 0;
  264.  
  265.     for (i = 0; i < len; i++) {
  266.         /* Collapse and ignore \ and CR. */
  267.         if (file[i] == '\\' && (i+1 < len) && file[i+1] == '\n') {
  268.             i++;
  269.             continue;
  270.         }
  271.  
  272.         /* Ignore whitespace */
  273.         if (isspace(file[i]))
  274.             continue;
  275.  
  276.         /* Handle strings as whole units */
  277.         if (file[i] == '"') {
  278.             i += parse_string(file+i, len - i, md);
  279.             continue;
  280.         }
  281.  
  282.         /* Comments: ignore */
  283.         if (file[i] == '/' && file[i+1] == '*') {
  284.             i += parse_comment(file+i, len - i);
  285.             continue;
  286.         }
  287.  
  288.         add_char(file[i], md);
  289.     }
  290.     release_file(file, len);
  291.     return 1;
  292. }
  293. /* Check whether the file is a static library or not */
  294. static int is_static_library(const char *objfile)
  295. {
  296.     int len = strlen(objfile);
  297.     if (objfile[len - 2] == '.' && objfile[len - 1] == 'a')
  298.         return 1;
  299.     else
  300.         return 0;
  301. }
  302.  
  303. /* We have dir/file.o.  Open dir/.file.o.cmd, look for deps_ line to
  304.  * figure out source file. */
  305. static int parse_source_files(const char *objfile, struct md4_ctx *md)
  306. {
  307.     char *cmd, *file, *line, *dir;
  308.     const char *base;
  309.     unsigned long flen, pos = 0;
  310.     int dirlen, ret = 0, check_files = 0;
  311.  
  312.     cmd = NOFAIL(malloc(strlen(objfile) + sizeof("..cmd")));
  313.  
  314.     base = strrchr(objfile, '/');
  315.     if (base) {
  316.         base++;
  317.         dirlen = base - objfile;
  318.         sprintf(cmd, "%.*s.%s.cmd", dirlen, objfile, base);
  319.     } else {
  320.         dirlen = 0;
  321.         sprintf(cmd, ".%s.cmd", objfile);
  322.     }
  323.     dir = NOFAIL(malloc(dirlen + 1));
  324.     strncpy(dir, objfile, dirlen);
  325.     dir[dirlen] = '\0';
  326.  
  327.     file = grab_file(cmd, &flen);
  328.     if (!file) {
  329.         warn("could not find %s for %s\n", cmd, objfile);
  330.         goto out;
  331.     }
  332.  
  333.     /* There will be a line like so:
  334.         deps_drivers/net/dummy.o := \
  335.           drivers/net/dummy.c \
  336.             $(wildcard include/config/net/fastroute.h) \
  337.           include/linux/config.h \
  338.             $(wildcard include/config/h.h) \
  339.           include/linux/module.h \
  340.  
  341.        Sum all files in the same dir or subdirs.
  342.     */
  343.     while ((line = get_next_line(&pos, file, flen)) != NULL) {
  344.         char* p = line;
  345.         if (strncmp(line, "deps_", sizeof("deps_")-1) == 0) {
  346.             check_files = 1;
  347.             continue;
  348.         }
  349.         if (!check_files)
  350.             continue;
  351.  
  352.         /* Continue until line does not end with '\' */
  353.         if ( *(p + strlen(p)-1) != '\\')
  354.             break;
  355.         /* Terminate line at first space, to get rid of final ' \' */
  356.         while (*p) {
  357.                        if (isspace(*p)) {
  358.                 *p = '\0';
  359.                 break;
  360.             }
  361.             p++;
  362.         }
  363.  
  364.         /* Check if this file is in same dir as objfile */
  365.         if ((strstr(line, dir)+strlen(dir)-1) == strrchr(line, '/')) {
  366.             if (!parse_file(line, md)) {
  367.                 warn("could not open %s: %s\n",
  368.                      line, strerror(errno));
  369.                 goto out_file;
  370.             }
  371.  
  372.         }
  373.  
  374.     }
  375.  
  376.     /* Everyone parsed OK */
  377.     ret = 1;
  378. out_file:
  379.     release_file(file, flen);
  380. out:
  381.     free(dir);
  382.     free(cmd);
  383.     return ret;
  384. }
  385.  
  386. /* Calc and record src checksum. */
  387. void get_src_version(const char *modname, char sum[], unsigned sumlen)
  388. {
  389.     void *file;
  390.     unsigned long len;
  391.     struct md4_ctx md;
  392.     char *sources, *end, *fname;
  393.     const char *basename;
  394.     char filelist[PATH_MAX + 1];
  395.     char *modverdir = getenv("MODVERDIR");
  396.  
  397.     if (!modverdir)
  398.         modverdir = ".";
  399.  
  400.     /* Source files for module are in .tmp_versions/modname.mod,
  401.        after the first line. */
  402.     if (strrchr(modname, '/'))
  403.         basename = strrchr(modname, '/') + 1;
  404.     else
  405.         basename = modname;
  406.     sprintf(filelist, "%s/%.*s.mod", modverdir,
  407.         (int) strlen(basename) - 2, basename);
  408.  
  409.     file = grab_file(filelist, &len);
  410.     if (!file)
  411.         /* not a module or .mod file missing - ignore */
  412.         return;
  413.  
  414.     sources = strchr(file, '\n');
  415.     if (!sources) {
  416.         warn("malformed versions file for %s\n", modname);
  417.         goto release;
  418.     }
  419.  
  420.     sources++;
  421.     end = strchr(sources, '\n');
  422.     if (!end) {
  423.         warn("bad ending versions file for %s\n", modname);
  424.         goto release;
  425.     }
  426.     *end = '\0';
  427.  
  428.     md4_init(&md);
  429.     while ((fname = strsep(&sources, " ")) != NULL) {
  430.         if (!*fname)
  431.             continue;
  432.         if (!(is_static_library(fname)) &&
  433.                 !parse_source_files(fname, &md))
  434.             goto release;
  435.     }
  436.  
  437.     md4_final_ascii(&md, sum, sumlen);
  438. release:
  439.     release_file(file, len);
  440. }
  441.  
  442. static void write_version(const char *filename, const char *sum,
  443.               unsigned long offset)
  444. {
  445.     int fd;
  446.  
  447.     fd = open(filename, O_RDWR);
  448.     if (fd < 0) {
  449.         warn("changing sum in %s failed: %s\n",
  450.             filename, strerror(errno));
  451.         return;
  452.     }
  453.  
  454.     if (lseek(fd, offset, SEEK_SET) == (off_t)-1) {
  455.         warn("changing sum in %s:%lu failed: %s\n",
  456.             filename, offset, strerror(errno));
  457.         goto out;
  458.     }
  459.  
  460.     if (write(fd, sum, strlen(sum)+1) != strlen(sum)+1) {
  461.         warn("writing sum in %s failed: %s\n",
  462.             filename, strerror(errno));
  463.         goto out;
  464.     }
  465. out:
  466.     close(fd);
  467. }
  468.  
  469. static int strip_rcs_crap(char *version)
  470. {
  471.     unsigned int len, full_len;
  472.  
  473.     if (strncmp(version, "$Revision", strlen("$Revision")) != 0)
  474.         return 0;
  475.  
  476.     /* Space for version string follows. */
  477.     full_len = strlen(version) + strlen(version + strlen(version) + 1) + 2;
  478.  
  479.     /* Move string to start with version number: prefix will be
  480.      * $Revision$ or $Revision: */
  481.     len = strlen("$Revision");
  482.     if (version[len] == ':' || version[len] == '$')
  483.         len++;
  484.     while (isspace(version[len]))
  485.         len++;
  486.     memmove(version, version+len, full_len-len);
  487.     full_len -= len;
  488.  
  489.     /* Preserve up to next whitespace. */
  490.     len = 0;
  491.     while (version[len] && !isspace(version[len]))
  492.         len++;
  493.     memmove(version + len, version + strlen(version),
  494.         full_len - strlen(version));
  495.     return 1;
  496. }
  497.  
  498. /* Clean up RCS-style version numbers. */
  499. void maybe_frob_rcs_version(const char *modfilename,
  500.                 char *version,
  501.                 void *modinfo,
  502.                 unsigned long version_offset)
  503. {
  504.     if (strip_rcs_crap(version))
  505.         write_version(modfilename, version, version_offset);
  506. }
  507.